package com.bifrost.service.impl;

import com.bifrost.entity.*;
import com.bifrost.model.ro.PromotionRO;
import com.bifrost.model.ro.PromotionSkuRO;
import com.bifrost.model.vo.PageVO;
import com.bifrost.model.vo.PromotionSkuVO;
import com.bifrost.model.vo.PromotionVO;
import com.bifrost.repository.MerchantStoreRepository;
import com.bifrost.repository.ProductSkuRepository;
import com.bifrost.repository.PromotionRepository;
import com.bifrost.repository.PromotionSkuRepository;
import com.bifrost.service.AdminPromotionService;
import com.bifrost.util.DateUtils;
import com.bifrost.util.TransformUtils;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author wqhe
 */
@Service("adminPromotionService")
public class AdminPromotionServiceImpl implements AdminPromotionService {

    @Autowired
    private PromotionSkuRepository promotionSkuRepository;
    @Autowired
    private PromotionRepository promotionRepository;
    @Autowired
    private ProductSkuRepository productSkuRepository;
    @Autowired
    private MerchantStoreRepository merchantStoreRepository;

    private static final ReentrantLock REENTRANT_LOCK= new ReentrantLock(true);
    /**
     * 分页查询所有促销商品
     * @return
     */
    @Override
    public PageVO list(MerchantStore merchantStore, String productCode, String productName, String startTime, String endTime, Integer pageCode, Integer pageSize) {
        Pageable pageable = new PageRequest(pageCode-1,pageSize, Sort.Direction.DESC,"updatedTimestamp");
        Specification<PromotionSku> specification = new Specification<PromotionSku>() {
            @Override
            public Predicate toPredicate(Root<PromotionSku> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();
                //对应门店条件
                Join<PromotionSku, Promotion> promotion = root.join("promotion", JoinType.INNER);
                Join<PromotionSku, MerchantStore> storeJoin = promotion.join("merchantStore", JoinType.INNER);
                predicates.add(cb.equal(storeJoin.get("merchantId"),merchantStore.getMerchantId()));

                if(!StringUtils.isBlank(productCode)){
                    //增加查询条件SKUCode
                    Join<PromotionSku,ProductSku> join = root.join("productSku", JoinType.INNER);
                    Path<String> queryProductSkuExternalId = join.get("externalId");
                    predicates.add(cb.like(queryProductSkuExternalId,"%"+productCode.trim()+"%"));
                }
                if(!StringUtils.isBlank(productName)){
                    //增加查询条件：商品名
                    Join<PromotionSku,ProductSku> join = root.join("productSku", JoinType.INNER);
                    ;
                    predicates.add(cb.or(cb.like(join.get("keyword"),"%"+productName.trim()+"%"),cb.like(join.get("skuName"),"%"+productName.trim()+"%")));
                }
                if(!StringUtils.isBlank(startTime)){
                    //增加查询条件：促销开始时间
                    Join<PromotionSku,Promotion> join = root.join("promotion", JoinType.INNER);
                    Path<Date> queryProductSkuName = join.get("startTime");
                    Date startDate = DateUtils.parse(startTime, DateUtils.DEFAULT_DATE_FORMAT);
                    predicates.add(cb.lessThanOrEqualTo(queryProductSkuName,startDate));
                }
                if(!StringUtils.isBlank(endTime)){
                    //增加查询条件：促销结束时间
                    Join<PromotionSku,Promotion> join = root.join("promotion", JoinType.INNER);
                    Path<Date> queryProductSkuName = join.get("endTime");
                    Date endDate = DateUtils.parse(endTime, DateUtils.DEFAULT_DATE_FORMAT);
                    predicates.add(cb.greaterThanOrEqualTo(queryProductSkuName,endDate));
                }
                Predicate[] p = new Predicate[predicates.size()];
                return cb.and(predicates.toArray(p));
            }
        };
        Page<PromotionSku> promotionSkus = promotionSkuRepository.findAll(specification, pageable);
        //判断有无数据
        if(CollectionUtils.isEmpty(promotionSkus.getContent())){
            return null;
        }
        Long totalElemement = promotionSkus.getTotalElements();
        //组装返回数据
        List<PromotionSkuVO> promotionSkuVOArrayList = new ArrayList<>();
        promotionSkus.forEach(promotionSku -> {
            PromotionSkuVO promotionSkuVO = new PromotionSkuVO();
            BeanUtils.copyProperties(promotionSku,promotionSkuVO);
            Promotion promotion = promotionSku.getPromotion();
            if(promotion != null){
                //设置promotionVO
                PromotionVO promotionVO = new PromotionVO();
                BeanUtils.copyProperties(promotion,promotionVO);
                //设置促销活动startTime
                promotionVO.setStartTime(DateUtils.format(promotion.getStartTime(), DateUtils.DEFAULT_DATE_FORMAT));
                //设置促销活动的endTime
                promotionVO.setEndTime(DateUtils.format(promotion.getEndTime(), DateUtils.DEFAULT_DATE_FORMAT));
                //获取促销活动所属门店
                if(merchantStore != null){
                    //设置门店merchantStoreMessage
                    promotionVO.setMerchantStoreMessage("["+merchantStore.getExternalId()+"]"+merchantStore.getStoreName());
                    //设置门店merchantStoreId
                    promotionVO.setMerchantId(merchantStore.getMerchantId());
                }
                promotionSkuVO.setPromotionVO(promotionVO);
            }
            //获取商品SKU
            ProductSku productSku = promotionSku.getProductSku();
            if(productSku != null){
                //设置商品skuId
                promotionSkuVO.setSkuId(productSku.getSkuId());
                //设置商品skuName
                promotionSkuVO.setSkuName(productSku.getSkuName());
                //设置商品skuCode
                promotionSkuVO.setSkuCode(productSku.getSkuCode());
                //设置商品skuExternalId
                promotionSkuVO.setSkuExternalId(productSku.getExternalId());
            }
            promotionSkuVOArrayList.add(promotionSkuVO);
        });
        PageVO pageVO = new PageVO(pageCode,pageSize,totalElemement.intValue(),promotionSkuVOArrayList);
        return pageVO;
    }

    /**
     * 新增促销活动
     *
     * @param merchantStore
     * @param promotionRO
     * @param user
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public List<String> save(MerchantStore merchantStore, PromotionRO promotionRO, User user) {
        try {
            if(REENTRANT_LOCK.tryLock(5, TimeUnit.SECONDS)){
                try{
                    Promotion promotion = new Promotion();
                    //设置促销活动促销商品默认值
                    promotion.setPromotionSkus(new ArrayList<>());
                    //获取新添加促销活动的促销商品
                    List<PromotionSkuRO> promotionSkuROList = promotionRO.getPromotionSkuROs();
                    //存放已经存在了的促销商品的skuId
                    List<String> existSkuIds = new ArrayList<>();
                    if(!CollectionUtils.isEmpty(promotionSkuROList)){
                        Specification<PromotionSku> specification = new Specification<PromotionSku>() {
                            @Override
                            public Predicate toPredicate(Root<PromotionSku> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                                List<Predicate> predicates = new ArrayList<>();
                                //过滤无效促销商品
                                predicates.add(cb.or(cb.isNull(root.get("archived")),cb.isFalse(root.get("archived"))));
                                List<Predicate> predicateList = new ArrayList<>();
                                Join<PromotionSku, Promotion> promotion = root.join("promotion", JoinType.INNER);
                                predicates.add(cb.or(cb.isNull(promotion.get("archived")),cb.isFalse(promotion.get("archived"))));
                                //对应门店条件
                                Join<PromotionSku, MerchantStore> storeJoin = promotion.join("merchantStore", JoinType.INNER);
                                predicates.add(cb.equal(storeJoin.get("merchantId"),merchantStore.getMerchantId()));
                                //增加查询条件SKUId
                                Join<PromotionSku,ProductSku> join = root.join("productSku", JoinType.INNER);
                                Path<Long> queryProductSkuId = join.get("skuId");
                                promotionSkuROList.forEach(promotionSkuRO -> {
                                    predicateList.add(cb.equal(queryProductSkuId,promotionSkuRO.getSkuId()));
                                });
                                Predicate[] p1 = new Predicate[predicateList.size()];
                                Predicate or = cb.or(predicateList.toArray(p1));
                                predicates.add(or);
                                //添加查询条件起止时间
                                Join<PromotionSku,Promotion> joinTime = root.join("promotion", JoinType.INNER);
                                Path<Date> queryStartTime = joinTime.get("startTime");
                                Path<Date> queryEndTime = joinTime.get("endTime");
                                Date startTime = DateUtils.parse(promotionRO.getStartTime(), DateUtils.DEFAULT_DATE_FORMAT);
                                Date endTime = DateUtils.parse(promotionRO.getEndTime(), DateUtils.DEFAULT_DATE_FORMAT);
                                //获取起止时间毫秒数
                                Long startTimeNum = startTime.getTime();
                                Long endTimeNum = endTime.getTime();
                                if(startTimeNum > endTimeNum){
                                    throw new RuntimeException("开始时间不能大于结束时间");
                                }
                                //新增促销商品开始时间大于其他促销活动结束时间或者促销商品结束时间小于开始时间则为可以添加的商品，相反为不可以添加的商品
                                predicates.add(cb.not(cb.or(cb.lessThan(queryEndTime,startTime),cb.greaterThan(queryStartTime,endTime))));
                                Predicate[] p = new Predicate[predicates.size()];
                                return cb.and(predicates.toArray(p));
                            }
                        };
                        List<PromotionSku> promotionSkus = promotionSkuRepository.findAll(specification);
                        if(!CollectionUtils.isEmpty(promotionSkus)){
                            promotionSkus.forEach(promotionSku -> {
                                existSkuIds.add("["+promotionSku.getProductSku().getExternalId()+"]"+promotionSku.getProductSku().getSkuName());
                            });
                        }else{
                            //没有冲突商品
                            BeanUtils.copyProperties(promotionRO,promotion);
                            //设置促销活动创建时间
                            promotion.setCreatedTimestamp(new Date());
                            if(merchantStore == null){
                                throw new RuntimeException("门店信息为空");
                            }
                            //设置促销活动所属门店
                            promotion.setMerchantStore(merchantStore);
                            //设置促销活动起止时间
                            promotion.setStartTime(DateUtils.parse(promotionRO.getStartTime(), DateUtils.DEFAULT_DATE_FORMAT));
                            promotion.setEndTime(DateUtils.parse(promotionRO.getEndTime(), DateUtils.DEFAULT_DATE_FORMAT));
                            Promotion savePromotion = promotionRepository.save(promotion);
                            promotion.setUpdatedBy(user.getAdminName());
                            promotion.setCreatedTimestamp(new Date());
                            promotion.setUpdatedTimestamp(new Date());
                            List<PromotionSkuRO> promotionSkuROS = promotionRO.getPromotionSkuROs();
                            promotionSkuROS.forEach(promotionSkuRO -> {
                                ProductSku productSku = productSkuRepository.findOne(promotionSkuRO.getSkuId());
                                if (productSku == null){
                                    throw new RuntimeException("商品skuId错误");
                                }
                                PromotionSku promotionSku = new PromotionSku();
                                BeanUtils.copyProperties(promotionSkuRO,promotionSku);
                                //设置促销商品的商品sku
                                promotionSku.setProductSku(productSku);
                                promotionSku.setProduct(productSku.getProduct());
                                promotionSku.setCreatedTimestamp(new Date());
                                promotionSku.setUpdatedTimestamp(new Date());
                                promotionSku.setUpdatedBy(user.getAdminName());

                                if(promotionSkuRO.getInventory()==0){
                                    promotionSku.setInventory(Integer.MAX_VALUE);
                                    promotionSku.setInventoryAvailable(Integer.MAX_VALUE);
                                }
                                if(promotionSkuRO.getHasLimit()&&promotionSkuRO.getLimitQuantity()==0){
                                    promotionSkuRO.setLimitQuantity(Integer.MAX_VALUE);
                                }
                                //保存促销商品到促销
                                promotion.getPromotionSkus().add(promotionSku);
                                promotionSku.setPromotion(savePromotion);
                                promotionSkuRepository.save(promotionSku);
                            });
                        }
                        return existSkuIds;
                    }
                    return existSkuIds;
                }catch (Exception e){
                    throw  e;
                }finally {
                    REENTRANT_LOCK.unlock();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 不分页的展示所有促销活动
     * @param type
     * @return
     */
    @Override
    public List<PromotionSkuVO> listAll(String type) {
        Specification<PromotionSku> specification = new Specification<PromotionSku>() {
            @Override
            public Predicate toPredicate(Root<PromotionSku> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();
                if(StringUtils.isNotEmpty(type)){
                    //增加查询条件：促销结束时间
                    Join<PromotionSku,Promotion> join = root.join("promotion", JoinType.INNER);
                    Path<Date> queryProductType = join.get("type");
                    predicates.add(cb.equal(queryProductType,type));
                }
                Predicate[] p = new Predicate[predicates.size()];
                return cb.and(predicates.toArray(p));
            }
        };

        List<PromotionSku> promotionSkuList = promotionSkuRepository.findAll(specification);
        List<PromotionSkuVO> promotionSkuVOList = Lists.newArrayList();
        if(CollectionUtils.isNotEmpty(promotionSkuList)) {
            promotionSkuList.forEach(promotionSku -> {
                PromotionSkuVO promotionSkuVO = TransformUtils.transfromToPromoitonSkuVo(promotionSku);
                promotionSkuVOList.add(promotionSkuVO);
            });
        }

        return promotionSkuVOList;
    }

}
